/*
 * Copyright (C) 2008 by Xume.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.xume.critann.jpa;

import java.util.Collection;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.FlushModeType;

import org.xume.critann.CriteriaBuilder;
import org.xume.critann.MatchMode;
import org.xume.critann.jpa.criteria.Criteria;
import org.xume.critann.jpa.criteria.Order;
import org.xume.critann.jpa.criteria.criterion.Conjunction;
import org.xume.critann.jpa.criteria.criterion.Criterion;
import org.xume.critann.jpa.criteria.criterion.Disjunction;
import org.xume.critann.jpa.criteria.criterion.InCriterion;
import org.xume.critann.jpa.criteria.criterion.LikeCriterion;
import org.xume.critann.jpa.criteria.criterion.SimpleCriterion;
import org.xume.critann.jpa.criteria.projection.Projection;
import org.xume.critann.jpa.criteria.projection.Property;
import org.xume.critann.jpa.criteria.projection.RowCount;
import org.xume.critann.jpa.criteria.projection.SimpleProjection;

/**
 * $Id: JpaCriteriaBuilder.java 24 2008-10-13 21:35:18Z johan.siebens $
 * 
 * @author Johan Siebens
 */
public class JpaCriteriaBuilder implements CriteriaBuilder<Criterion, Projection> {

	private Criteria criteria;

	public JpaCriteriaBuilder(EntityManager entityManager, Class<?> entityClass) {
		this.criteria = new Criteria(entityClass, entityManager);
	}

	public JpaCriteriaBuilder addCriterion(Criterion criterion) {
		this.criteria.add(criterion);
		return this;
	}

	public Projection avg(String propertyName) {
		return new SimpleProjection("avg", propertyName);
	}

	public Criterion conjunction(List<Criterion> criterions) {
		return new Conjunction(criterions);
	}

	public Projection count(String propertyName) {
		return new SimpleProjection("count", propertyName);
	}

	public Criterion disjunction(List<Criterion> criterions) {
		return new Disjunction(criterions);
	}

	public Criterion eq(String propertyName, Object propertyValue) {
		return new SimpleCriterion(propertyName, "=", propertyValue);
	}

	public Criterion ge(String propertyName, Object propertyValue) {
		return new SimpleCriterion(propertyName, ">=", propertyValue);
	}

	public Criterion gt(String propertyName, Object propertyValue) {
		return new SimpleCriterion(propertyName, ">", propertyValue);
	}

	public Criterion ilike(String propertyName, String propertyValue, MatchMode matchMode) {
		return new LikeCriterion(propertyName, propertyValue, matchMode, true);
	}

	public Criterion le(String propertyName, Object propertyValue) {
		return new SimpleCriterion(propertyName, "<=", propertyValue);
	}

	public Criterion like(String propertyName, String propertyValue, MatchMode matchMode) {
		return new LikeCriterion(propertyName, propertyValue, matchMode, false);
	}

	public List<?> list() {
		return this.criteria.list();
	}

	public Criterion lt(String propertyName, Object propertyValue) {
		return new SimpleCriterion(propertyName, "<", propertyValue);
	}

	public Projection max(String propertyName) {
		return new SimpleProjection("max", propertyName);
	}

	public Projection min(String propertyName) {
		return new SimpleProjection("min", propertyName);
	}

	public Criterion ne(String propertyName, Object propertyValue) {
		return new SimpleCriterion(propertyName, "<>", propertyValue);
	}

	public Projection property(String propertyName) {
		return new Property(propertyName);
	}

	public Projection rowCount() {
		return new RowCount();
	}

	public JpaCriteriaBuilder setFirstResult(int firstResult) {
		this.criteria.setFirstResult(firstResult);
		return this;
	}

	public JpaCriteriaBuilder setMaxResults(int maxResults) {
		this.criteria.setMaxResults(maxResults);
		return this;
	}

	public JpaCriteriaBuilder setOrderBy(String property) {
		this.criteria.addOrder(Order.asc(property));
		return this;
	}

	public JpaCriteriaBuilder setProjection(Projection projection) {
		this.criteria.setProjection(projection);
		return this;
	}

	public Projection sum(String propertyName) {
		return new SimpleProjection("sum", propertyName);
	}

	public Object uniqueResult() {
		return this.criteria.uniqueResult();
	}

	public JpaCriteriaBuilder setFlushMode(FlushModeType flushModeType) {
		this.criteria.setFlushMode(flushModeType);
		return this;
	}

	public JpaCriteriaBuilder setHint(String name, Object value) {
		this.criteria.setHint(name, value);
		return this;
	}

	public Criterion in(String propertyName, Collection<?> values) {
		return new InCriterion(propertyName, values.toArray());
	}

	public Criterion in(String propertyName, Object[] values) {
		return new InCriterion(propertyName, values);
	}

}
